//NOTES:
//Shadows have been *temporarily* dropped, in order to facilitate progress in other aspects of the mod!

// This is used by 3dsmax to load the correct parser
string ParamID = "0x003";

#include "defines.fxh"

int maxaniso = 1;//max anisotropy
int filtermin = 2;//anisotropic = 3, linear = 2
int filtermag = 2;
int filtermip = 2;//linear

//////////////////////////////////////////////////
//Matrices
//////////////////////////////////////////////////
float4x4 WorldIT : WorldInverseTranspose < string UIWidget = "None"; >;
float4x4 WorldViewProj : WorldViewProjection < string UIWidget = "None"; >;
float4x4 World : World < string UIWidget = "None"; >;
float4x4 ViewInv : ViewInverse < string UIWidget = "None"; >;

//////////////////////////////////////////////////
//Main Light
//////////////////////////////////////////////////
float3 LightDir : Direction
<
	string Object = "Spotlight";
	string Space = "World";
> = {0.0f, 0.5, -1.0f};//{0.0f, 1.0f, -0.5f};

float4 LightColor1 : Diffuse <
    string UIName =  "Light1 Color";
    string Object = "Spotlight";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

float3 spec2dir : Direction
<
	string Object = "SpotLight";
	string Space = "World";
> = {0.0f,0.0f,1.0f};

//////////////////////////////////////////////////
//Material surface
//////////////////////////////////////////////////

float4 MatDiffuse : Diffuse
<
    string UIName =  "Material Diffuse";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 0.0f};

float4 MatAmbient : Ambient
<
    string UIName =  "Material Ambient";
    string UIWidget = "Color";
> = {0.0f, 0.0f, 0.0f, 1.0f};

float4 MatSpec : Specular
<
    string UIName =  "Material Specular";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

float4 MatEmissive : Emissive
<
    string UIName =  "Material Emissive";
    string UIWidget = "Color";
> = {0.0f, 0.0f, 0.0f, 1.0f};

float4 AltMatSpec : Specular
<
    string UIName =  "Second Specular";
    string UIWidget = "Color";
> = {0.0f, 0.0f, 0.0f, 0.0f};//{0.7f, 0.8f, 1.00f, 1.0f};

float MatSpecPow : SpecularPower <
    string UIWidget = "slider";
    float UIMin = 1.0;
    float UIMax = 128.0;
    float UIStep = 1.0;
    string UIName =  "specular power";
> = 40.0;

float AltMatSpecPow : SpecularPower <
    string UIWidget = "slider";
    float UIMin = 1.0;
    float UIMax = 128.0;
    float UIStep = 1.0;
    string UIName =  "specular power 2";
> = 80.0;

float refmult : Environment
<
    string UIWidget = "slider";
    float UIMin = 0.0f;
    float UIMax = 2.0f;
    float UIStep = 0.001f;
    string UIName = "Reflection Multiplier";
> = 0.5f;

float fresnel
<
    string UIWidget = "slider";
    float UIMin = 0.0f;
    float UIMax = 100.0f;
    float UIStep = 0.001f;
    string UIName = "Fresnel";
> = 15.0f;

float edgeref
<
    string UIWidget = "slider";
    float UIMin = 0.0f;
    float UIMax = 100.0f;
    float UIStep = 0.001f;
    string UIName = "Edge Reflection";
> = 2.0f;

//global colors
float4 sceneambient
<
    string UIName =  "Scene Ambient";
    string UIWidget = "Color";
> = {0.0f, 0.0f, 0.0f, 1.0f};

float4 skyrgb
<
    string UIName =  "Sky Color";
    string UIWidget = "Color";
> = {0.5f, 0.75f, 1.0f, 1.0f};

//////////////////////////////////////////////////
//Textures
//////////////////////////////////////////////////

texture colorTexture : Diffuse <
    string ResourceName = "default_color.dds";
    string ResourceType = "2D";
>;

texture refcubeTexture : Environment <
    string ResourceName = "default_reflection.dds";
    string ResourceType = "CUBE";
>;

texture normalTexture : Normal <
    string ResourceName = "default_bump_normal.dds";
    string ResourceType = "2D";
>;

//////////////////////////////////////////////////
//Samplers - need to sync filter/addressing w/game
//////////////////////////////////////////////////

sampler2D colorSampler = sampler_state {
	Texture = <colorTexture>;
	MinFilter = <filtermin>;
	MagFilter = <filtermag>;
	MipFilter = <filtermip>;
	AddressU = Wrap;
	AddressV = Wrap;
	AddressW = Wrap;
	MIPMAPLODBIAS = 0.0f;
	MAXMIPLEVEL = 0;
	BORDERCOLOR = 0xFF000000;//argb
	MaxAnisotropy = <maxaniso>;
};

samplerCUBE envSampler = sampler_state {
	Texture = <refcubeTexture>;
	MinFilter = <filtermin>;
	MagFilter = <filtermag>;
	MipFilter = <filtermip>;
	AddressU = Wrap;
	AddressV = Wrap;
	AddressW = Wrap;
	MIPMAPLODBIAS = 0.0f;
	MAXMIPLEVEL = 0;
	BORDERCOLOR = 0xFF000000;//argb
	MaxAnisotropy = <maxaniso>;
};

sampler2D normalSampler = sampler_state {
	Texture = <normalTexture>;
	MinFilter = <filtermin>;
	MagFilter = <filtermag>;
	MipFilter = <filtermip>;
	AddressU = Wrap;
	AddressV = Wrap;
	AddressW = Wrap;
	MIPMAPLODBIAS = 0.0f;
	MAXMIPLEVEL = 0;
	BORDERCOLOR = 0xFF000000;//argb
	MaxAnisotropy = <maxaniso>;
};

//////////////////////////////////////////////////
//Structures
//////////////////////////////////////////////////

//Vertex structure from game
struct appdata {
    float3 Position	: POSITION;
    float3 UV		: TEXCOORD0;
    float4 Normal	: NORMAL;
    //float4 Binormal	: BINORMAL0;
    //float4 Tangent	: TANGENT0;
};

//data passed from the vertex shader to the pixel shader
struct vertexOutput {
    float4 HPosition	: POSITION;
    float3 TexCoord	: TEXCOORD0;
    float3 LightVec1	: TEXCOORD1;
    float3 WorldNormal	: TEXCOORD2;
    float3 WorldPos	: TEXCOORD3;
    float3 WorldEyePos	: TEXCOORD4;
    float3 Spec2Vec		: TEXCOORD5;
    //float3 WorldTangent	: TEXCOORD5;
    //float3 WorldBinorm	: TEXCOORD6;
};

//////////////////////////////////////////////////
//Shaders
//////////////////////////////////////////////////

//Vertex Shader
vertexOutput mainVS(appdata IN)
{	
	vertexOutput OUT;
    OUT.WorldNormal = mul(IN.Normal, WorldIT).xyz;
    float4 Po = float4(IN.Position.xyz,1.0);
    float4 Pw = mul(Po, World);
    OUT.WorldPos = Pw;
    OUT.LightVec1 = normalize(-LightDir);
    OUT.TexCoord = IN.UV;
    OUT.WorldEyePos = ViewInv[3].xyz;
    OUT.HPosition = mul(Po, WorldViewProj);
    OUT.Spec2Vec = normalize(spec2dir);
    return OUT;
}

//Bump Pixel Shader no reflection
float4 mainPSB(vertexOutput IN) : COLOR
{	
    float4 map = tex2D(colorSampler,IN.TexCoord.xy);
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    //normal map
    float3 bumps = tex2D(normalSampler,IN.TexCoord.xy).xyz - (0.5).xxx;
    Nn = Nn + (bumps.x + bumps.y);
    //Nn = normalize(Nn);
    
    //float3 cbumps = ComputeNormalsPS(IN.TexCoord.xy);
    //Nn = Nn * cbumps;
    //Nn = Nn + (bumps.x + bumps.y);
    Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * MatSpec);//MatSpec
    
    //Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient * map) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse * map) * diffContrib);
    specularlight = specContrib * (diffContrib);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a * map.a;
	
	return finalcolor;
}

//Bump Pixel Shader no reflection, no diffuse tex
float4 mainPSB_notex(vertexOutput IN) : COLOR
{	
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    //normal map
    float3 bumps = tex2D(normalSampler,IN.TexCoord.xy).xyz - (0.5).xxx;
    Nn = Nn + (bumps.x + bumps.y);
    //Nn = normalize(Nn);
    
    //float3 cbumps = ComputeNormalsPS(IN.TexCoord.xy);
    //Nn = Nn * cbumps;
    //Nn = Nn + (bumps.x + bumps.y);
    Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * MatSpec);//MatSpec
    
    //Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient ) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse ) * diffContrib);
    specularlight = specContrib * (diffContrib);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a;
	
	return finalcolor;
}

//Bump Shiny Pixel Shader
float4 mainPSBS(vertexOutput IN) : COLOR
{
    float4 map = tex2D(colorSampler,IN.TexCoord.xy);
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    //normal map - is tangent space, will need to adjust later
    float4 bumps = tex2D(normalSampler,IN.TexCoord.xy);
    //Nn = Nn + (bumps.x + bumps.y);
    //Nn = normalize(Nn);
    
    //expand normal to -1/+1 range and normalize
    bumps = normalize(2.0f*bumps - 1.0f);
    
    //Nn = Nn + (bumps.x + bumps.y);
    Nn.x = Nn.x + bumps.x;
    Nn.y = Nn.y + bumps.y;
   	Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
	//spec2
    float3 Ln2 = normalize(IN.Spec2Vec);
    float3 Hn2 = normalize(Vn + Ln2);
    //float hdn = pow(max(0,dot(Hn2,Nn)),MatSpecPow);// * 1.0f;
    //float ldn = dot(Ln,Nn);
    //ldn = max(0.0,ldn);
    //float3 Hn2 = normalize(Vn + Ln.xyz);//use camera input
    float hdn2 = pow(max(0,dot(Hn2,Nn)),AltMatSpecPow);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * (MatSpec * 1.0f));//MatSpec
    float4 spec2 = (ldn * hdn2) * (LightColor1 * (AltMatSpec * 1.0f));//AltMatSpec
    specContrib += spec2;
    
	//reflection map coordinates are flipped and swizzled for GTA
	float3 refvect = reflect(Vn,Nn);
	refvect.xyz = refvect.xzy;//this is expensive. it's either this, or multiple lights, but not both (under sm20)
	//refvect = (refvect * ViewInv);
	float4 reflColor = texCUBE(envSampler,-refvect.xyz);
	
	float vdn = dot(Vn,Nn);
	float fres = (reflColor * edgeref) * pow(1-abs(vdn),fresnel);
	
	#ifdef MASKREF
		reflColor = reflColor * 1.0f;
	#endif
	
	//Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient * map) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse * map) * diffContrib);
    specularlight = specContrib * (diffContrib) + ((reflColor * refmult) + fres);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a * map.a;

	return finalcolor;
}

//Bump Shiny Pixel Shader no diffuse tex
float4 mainPSBS_notex(vertexOutput IN) : COLOR
{
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    //normal map - is tangent space, will need to adjust later
    float4 bumps = tex2D(normalSampler,IN.TexCoord.xy).xyzw - (0.5).xxxx;
    //Nn = Nn + (bumps.x + bumps.y);
    //Nn = normalize(Nn);
    
    Nn = Nn + (bumps.x + bumps.y);
    Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
	//spec2
    float3 Ln2 = normalize(IN.Spec2Vec);
    float3 Hn2 = normalize(Vn + Ln2);
    //float hdn = pow(max(0,dot(Hn2,Nn)),MatSpecPow);// * 1.0f;
    //float ldn = dot(Ln,Nn);
    //ldn = max(0.0,ldn);
    //float3 Hn2 = normalize(Vn + Ln.xyz);//use camera input
    float hdn2 = pow(max(0,dot(Hn2,Nn)),AltMatSpecPow);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * (MatSpec * 1.0f));//MatSpec
    float4 spec2 = (ldn * hdn2) * (LightColor1 * (AltMatSpec * 1.0f));//AltMatSpec
    specContrib += spec2;
    
	//reflection map coordinates are flipped and swizzled for GTA
	float3 refvect = reflect(Vn,Nn);
	refvect.xyz = refvect.xzy;//this is expensive. it's either this, or multiple lights, but not both (under sm20)
	//refvect = (refvect * ViewInv);
	float4 reflColor = texCUBE(envSampler,-refvect.xyz);
	
	float vdn = dot(Vn,Nn);
	float fres = (reflColor * edgeref) * pow(1-abs(vdn),fresnel);
	
	//Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse) * diffContrib);
    specularlight = specContrib * (diffContrib) + ((reflColor * refmult) + fres);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a;

	return finalcolor;
}

//Bump Shiny Pixel Shader sm2
float4 mainPSBS20(vertexOutput IN) : COLOR
{
    float4 map = tex2D(colorSampler,IN.TexCoord.xy);
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * (MatSpec * 1.0f));//MatSpec
    
	//reflection map coordinates are flipped and swizzled for GTA
	float3 refvect = reflect(Vn,Nn);
	refvect.xyz = refvect.xzy;//this is expensive. it's either this, or multiple lights, but not both (under sm20)
	float4 reflColor = texCUBE(envSampler,-refvect.xyz);
	
	float vdn = dot(Vn,Nn);
	float fres = (reflColor * edgeref) * pow(1-abs(vdn),fresnel);
	
	#ifdef MASKREF
		reflColor = reflColor * 1.0f;
	#endif
	
	//Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient * map) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse * map) * diffContrib);
    specularlight = specContrib * (diffContrib) + ((reflColor * refmult) + fres);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a * map.a;

	return finalcolor;
}

//Bump Shiny Pixel Shader no diffuse tex sm2
float4 mainPSBS_notex20(vertexOutput IN) : COLOR
{
    float3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    float3 Nn = normalize(IN.WorldNormal);
    
    Nn = normalize(Nn);
    
    //calc light vec
    float3 Ln = normalize(IN.LightVec1.xyz);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),MatSpecPow);// * 1.0f;
    float ldn = dot(Ln,Nn);
    ldn = max(0.0,ldn);
    
    //blend sun light color
    float4 diffContrib = ldn * LightColor1;
    float4 specContrib = (ldn * hdn) * (LightColor1 * (MatSpec * 1.0f));//MatSpec
    
	//reflection map coordinates are flipped and swizzled for GTA
	float3 refvect = reflect(Vn,Nn);
	refvect.xyz = refvect.xzy;//this is expensive. it's either this, or multiple lights, but not both (under sm20)
	float4 reflColor = texCUBE(envSampler,-refvect.xyz);
	
	float vdn = dot(Vn,Nn);
	float fres = (reflColor * edgeref) * pow(1-abs(vdn),fresnel);
	
	#ifdef MASKREF
		reflColor = reflColor * 1.0f;
	#endif
	
	//Directx Fixed-Function lighting model
    float4 ambientlight, diffuselight, specularlight;
    ambientlight = (MatAmbient) * (sceneambient + LightColor1);
    diffuselight = ((MatDiffuse) * diffContrib);
    specularlight = specContrib * (diffContrib) + ((reflColor * refmult) + fres);
    
    float4 finalcolor = ambientlight + diffuselight + specularlight + MatEmissive;
    finalcolor.a = MatDiffuse.a;

	return finalcolor;
}

//////////////////////////////////////////////////
//Techniques - sm 20
//////////////////////////////////////////////////
technique VehicleBump20
{
	pass p0
	{
		#ifdef WIRE
		Fillmode = wireframe;
		#endif
		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_0 mainPSB();
	}
}

technique VehicleBump_notex20
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_0 mainPSB_notex();
	}
}

technique VehicleBumpShiny20
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_0 mainPSBS20();
	}
}

//glass
technique VehicleBumpShiny_notex20
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_0 mainPSBS_notex20();
	}
}

//////////////////////////////////////////////////
//Techniques - sm 2x
//////////////////////////////////////////////////
technique VehicleBump2x
{
	pass p0
	{
		#ifdef WIRE
		Fillmode = wireframe;
		#endif
		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_b mainPSB();
	}
}

technique VehicleBump_notex2x
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_b mainPSB_notex();
	}
}

technique VehicleBumpShiny2x
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_b mainPSBS();
	}
}

//glass
technique VehicleBumpShiny_notex2x
{
	pass p0
	{		
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_b mainPSBS_notex();
	}
}

//////////////////////////////////////////////////
//Techniques - 30
//////////////////////////////////////////////////

technique VehicleBump30
{
	pass p0
	{
		#ifdef WIRE
		Fillmode = wireframe;
		#endif
		
		VertexShader = compile vs_3_0 mainVS();
		PixelShader = compile ps_3_0 mainPSB();
	}
}

technique VehicleBump_notex30
{
	pass p0
	{		
		VertexShader = compile vs_3_0 mainVS();
		PixelShader = compile ps_3_0 mainPSB_notex();
	}
}

technique VehicleBumpShiny30
{
	pass p0
	{		
		VertexShader = compile vs_3_0 mainVS();
		PixelShader = compile ps_3_0 mainPSBS();
	}
}

technique VehicleBumpShiny_notex30
{
	pass p0
	{		
		VertexShader = compile vs_3_0 mainVS();
		PixelShader = compile ps_3_0 mainPSBS_notex();
	}
}